//
//  Planet.m
//  PezMonkey
//
//  Created by Spence DiNicolantonio on 12/23/09.
//  Copyright 2009 Necrosoft. All rights reserved.
//

#import "Planet.h"

#define kPlanetRadius 70
#define kPlanetGravity 0.4
#define kBoxCount 30


@implementation Planet

@synthesize planetBody;

- (NSString *)demoName {
	return @"Planet";
}

- (void)start {
	// create space
	self.space = [PMSpace space];
	[space setIterations:7];
	[space setActiveHashSize:10000 cellDimension:30];
	
	// create planet body
	self.planetBody = [PMBody staticBody];
	
	// apply angular velocity to planet body
	[planetBody setAngularVelocity:0.2];
	
	// add planet body to space
	[space addBody:planetBody];
	
	// create planet shape and add it to space
	PMShape *shape = [PMCircleShape circleShapeWithBody:planetBody 
												 radius:kPlanetRadius];
	[shape setFriction:1.0];
	[shape setElasticity:1.0];
	[shape setLayers:PMLayerMaskNotGrabbable];
	[space addShape:shape];
	
	// add boxes
	for (int i=0; i<kBoxCount; i++)
		[self addBox];
}

/**
 * create and add a box to the space at a random position.
 */
- (void)addBox {
	// define box attributes
	PMFloat width = 10.0;
	PMFloat mass = 1.0;
	
	// define box vertices
	NSUInteger vertCount = 4;
	PMVect verts[] = {
		PMVectMake(-width,-width),
		PMVectMake(-width, width),
		PMVectMake( width, width),
		PMVectMake( width,-width),
	};
	
	// calculate box moment
	PMFloat moment = PMMomentForPolygon(mass, verts, vertCount, PMVectZero);
	
	// create box body
	PMBody *body = [PMBody bodyWithMass:mass moment:moment];
	
	// set self as box body's delegate
	// (this is done to provide custom velocity updating to simulate gravitation
	// pull by the planet)
	body.delegate = self;
	
	// set random box position
	PMVect position;
	do {
		PMFloat xPos = (PMFloatRandom() * (640 - width / 2)) - (320 - width / 2);
		PMFloat yPos = (PMFloatRandom() * (480 - width / 2)) - (240 - width / 2);
		position = PMVectMake(xPos, yPos);
	} while (PMVectMag(position) < (kPlanetRadius + width / 2));
	[body setPosition:position];
	
	// set random box velocity
	PMFloat xVel = (2*PMFloatRandom() - 1) * 250;
	PMFloat yVel = (2*PMFloatRandom() - 1) * 250;
	[body setVelocity:PMVectMake(xVel, yVel)];
	
	// add box body to space
	[space addBody:body];
	
	// create box shape
	PMShape *shape = [PMPolygonShape polygonShapeWithBody:body 
												 vertices:verts 
											  vertCount:vertCount];
	[shape setFriction:0.7];
	[shape setElasticity:0.0];
	[space addShape:shape];
}


#pragma mark -
#pragma mark Dealloc

- (void)dealloc {
	[planetBody release];
	[super dealloc];
}


#pragma mark -
#pragma mark PMBody Delegate

/**
 * Custom velocity update used for box objects to simulate gravitational pull of
 * the planet.
 */
- (BOOL)body:(PMBody *)body willUpdateVelocityWithTime:(NSTimeInterval)time gravity:(PMVect)gravity damping:(PMFloat)damping {
	// determine gravity vector caused by planet
	PMVect planetGravity = PMVectWithMagDir(kPlanetGravity, 
											PMVectSub(planetBody.position, body.position));
	
	// calculate net gravity force vector
	PMVect newGravity = PMVectAdd(gravity, planetGravity);
	
	// update velocity with new gravity vector
	[body updateVelocityWithTime:time 
						 gravity:newGravity 
						 damping:damping];
	
	// return NO because we don't want the velocity to be updated
	// (we already did it)
	return NO;
}

@end
